package nsqd

import (
	"crypto/md5"
	"crypto/tls"
	"hash/crc32"
	"io"
	"log"
	"os"
	"time"

	"github.com/nsqio/nsq/internal/lg"
)

type Options struct {
	// basic options
	ID        int64  `flag:"node-id" cfg:"id"`
	LogLevel  string `flag:"log-level"`
	LogPrefix string `flag:"log-prefix"`
	Verbose   bool   `flag:"verbose"` // for backwards compatibility 启用详情日志
	Logger    Logger
	logLevel  lg.LogLevel // private, not really an option

	TCPAddress               string        `flag:"tcp-address"` // TCP 客户端 监听的 <addr>:<port>
	HTTPAddress              string        `flag:"http-address"` // 为 HTTP 客户端监听<addr>:<port>
	HTTPSAddress             string        `flag:"https-address"`//为 HTTPS 客户端 监听 <addr>:<port>
	BroadcastAddress         string        `flag:"broadcast-address"` // 通过 lookupd  注册的地址（默认名是 hostname）
	NSQLookupdTCPAddresses   []string      `flag:"lookupd-tcp-address" cfg:"nsqlookupd_tcp_addresses"` // lookupd  注册的地址,可能有多个
	AuthHTTPAddresses        []string      `flag:"auth-http-address" cfg:"auth_http_addresses"` // <addr>:<port> 查询授权服务器 (可能会给多次)
	HTTPClientConnectTimeout time.Duration `flag:"http-client-connect-timeout" cfg:"http_client_connect_timeout"` // 客户端【连接】超时时间
	HTTPClientRequestTimeout time.Duration `flag:"http-client-request-timeout" cfg:"http_client_request_timeout"` // 客户端【请求】超时时间

	// diskqueue options
	// 持久化磁盘的信息
	DataPath        string        `flag:"data-path"` //缓存消息的磁盘路径
	MemQueueSize    int64         `flag:"mem-queue-size"` // 内存中的消息数
	MaxBytesPerFile int64         `flag:"max-bytes-per-file"` // 每个磁盘队列文件的字节数  控制文件大小 (default 104857600)
	SyncEvery       int64         `flag:"sync-every"`	//  磁盘队列 fsync 的消息数 ？？
	SyncTimeout     time.Duration `flag:"sync-timeout"` // 每个磁盘队列 fsync 平均耗时

	// 扫描队列相关配置
	QueueScanInterval        time.Duration // 扫描间隔
	QueueScanRefreshInterval time.Duration // 刷新间隔
	QueueScanSelectionCount  int
	QueueScanWorkerPoolMax   int
	QueueScanDirtyPercent    float64

	// msg and command options
	// 消息与指令相关配置
	MsgTimeout    time.Duration `flag:"msg-timeout"` // 自动重新队列消息前需要等待的时间
	MaxMsgTimeout time.Duration `flag:"max-msg-timeout"` // 消息超时前的最大持续时间 (default 15m0s)
	MaxMsgSize    int64         `flag:"max-msg-size"` // 单个消息体的最大字节数 default 1048576
	MaxBodySize   int64         `flag:"max-body-size"` // 单个命令体的最大尺寸 (default 5242880)
	MaxReqTimeout time.Duration `flag:"max-req-timeout"` // 消息的最大请求超时时间  (default 1h0m0s)
	ClientTimeout time.Duration

	// client overridable configuration options
	//客户端可重写配置选项
	MaxHeartbeatInterval   time.Duration `flag:"max-heartbeat-interval"` // 客户端心跳之间的最大客户端可配置时间（默认值为1m0s）
	MaxRdyCount            int64         `flag:"max-rdy-count"` // 客户端最大RDY计数 default 2500
	MaxOutputBufferSize    int64         `flag:"max-output-buffer-size"` // 客户端输出缓冲区的最大客户端可配置大小（以字节为单位）（默认为65536）
	MaxOutputBufferTimeout time.Duration `flag:"max-output-buffer-timeout"` // 在刷新到客户端之间的最大客户端可配置时间（默认1 s）

	// statsd integration
	// 统计配置
	StatsdAddress       string        `flag:"statsd-address"` // 用于推动统计数据的statsd进程地址   UDP <addr>:<port>
	StatsdPrefix        string        `flag:"statsd-prefix"` // 用于发送到statsd的密钥的前缀
	StatsdInterval      time.Duration `flag:"statsd-interval"` //推到statsd之间的持续时间 （默认的“1m0s”）
	StatsdMemStats      bool          `flag:"statsd-mem-stats"` // 切换发送内存和GC统计数据到statsd（默认为true）
	StatsdUDPPacketSize int           `flag:"statsd-udp-packet-size"`

	// e2e message latency
	E2EProcessingLatencyWindowTime  time.Duration `flag:"e2e-processing-latency-window-time"` // 计算这段时间里，点对点时间延迟（例如，60s 仅计算过去 60 秒）
	E2EProcessingLatencyPercentiles []float64     `flag:"e2e-processing-latency-percentile" cfg:"e2e_processing_latency_percentiles"` // 消息处理时间的百分比（通过逗号可以多次指定，默认为 none

	// TLS config
	// TLS 配置
	TLSCert             string `flag:"tls-cert"` // 证书文件路径
	TLSKey              string `flag:"tls-key"` // 密钥文件路径
	TLSClientAuthPolicy string `flag:"tls-client-auth-policy"` // 客户端证书认证策略（“要求”或“需求验证”）
	TLSRootCAFile       string `flag:"tls-root-ca-file"` // 证书权威文件的路径
	TLSRequired         int    `flag:"tls-required"` // 要求TLS用于客户端连接（true、false、tcp-https）
	TLSMinVersion       uint16 `flag:"tls-min-version"` // 最小的ssl/tls版本，可接受（'ssl 3.0'、'tls 1.0'、'tls 1.1'或'tls 1.2'）（默认769）

	// compression  压缩
	DeflateEnabled  bool `flag:"deflate"` //启用压缩特性 （客户端压缩）（默认为true）
	MaxDeflateLevel int  `flag:"max-deflate-level"` // max压缩压缩级别，客户端可以协商（大于==nsqd CPU使用率）（默认6）
	SnappyEnabled   bool `flag:"snappy"` // 打开快速选项 (客户端压缩)
}

func NewOptions() *Options {
	hostname, err := os.Hostname()
	if err != nil {
		log.Fatal(err)
	}

	h := md5.New()
	io.WriteString(h, hostname)
	defaultID := int64(crc32.ChecksumIEEE(h.Sum(nil)) % 1024)

	return &Options{
		ID:        defaultID,
		LogPrefix: "[nsqd] ",
		LogLevel:  "info",

		TCPAddress:       "0.0.0.0:4150",
		HTTPAddress:      "0.0.0.0:4151",
		HTTPSAddress:     "0.0.0.0:4152",
		BroadcastAddress: hostname,

		NSQLookupdTCPAddresses: make([]string, 0),
		AuthHTTPAddresses:      make([]string, 0),

		HTTPClientConnectTimeout: 2 * time.Second,
		HTTPClientRequestTimeout: 5 * time.Second,

		MemQueueSize:    10000,
		MaxBytesPerFile: 100 * 1024 * 1024,
		SyncEvery:       2500,
		SyncTimeout:     2 * time.Second,

		QueueScanInterval:        100 * time.Millisecond,
		QueueScanRefreshInterval: 5 * time.Second,
		QueueScanSelectionCount:  20,
		QueueScanWorkerPoolMax:   4,
		QueueScanDirtyPercent:    0.25,

		MsgTimeout:    60 * time.Second,
		MaxMsgTimeout: 15 * time.Minute,
		MaxMsgSize:    1024 * 1024,
		MaxBodySize:   5 * 1024 * 1024,
		MaxReqTimeout: 1 * time.Hour,
		ClientTimeout: 60 * time.Second,

		MaxHeartbeatInterval:   60 * time.Second,
		MaxRdyCount:            2500,
		MaxOutputBufferSize:    64 * 1024,
		MaxOutputBufferTimeout: 1 * time.Second,

		StatsdPrefix:        "nsq.%s",
		StatsdInterval:      60 * time.Second,
		StatsdMemStats:      true,
		StatsdUDPPacketSize: 508,

		E2EProcessingLatencyWindowTime: time.Duration(10 * time.Minute),

		DeflateEnabled:  true,
		MaxDeflateLevel: 6,
		SnappyEnabled:   true,

		TLSMinVersion: tls.VersionTLS10,
	}
}
